#region

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using log4net;
using xConnected.Common.Country;
using xConnected.Common.Project;
using xConnected.Core.Interfaces.Paging;
using xConnected.Core.Model;
using xConnected.Core.Model.ViewModel.xConnected.Core.Model.ViewModel;
using xConnected.Service;

#endregion

namespace xConnected.Web.Controllers
{
    public class PositionController : ApiController
    {
        private readonly CategoryService _categoryService;
        private readonly CompanyProfileService _companyProfileService;
        private readonly CountryService _countryService;
        private readonly IndustryService _industryService;
        private readonly PositionService _positionService;
        private readonly TechnologyService _technologyService;
        private readonly TechnologySkillService _technologySkillService;
        private readonly UserService _userService;

        public PositionController(PositionService PositionService, CategoryService categoryService,
                                 TechnologyService technologyService, TechnologySkillService technologySkillService,
                                 CompanyProfileService companyProfileService,
                                 UserService userService, CountryService countryService, IndustryService industryService)
        {
            _positionService = PositionService;
            _categoryService = categoryService;
            _technologyService = technologyService;
            _technologySkillService = technologySkillService;
            _companyProfileService = companyProfileService;
            _userService = userService;
            _countryService = countryService;
            _industryService = industryService;
        }


        public IPage<Position> ListAdvancedSearchAll(AdvancedSearchModelPosition positionModel)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                //set profile model's userid to current user id 
                positionModel.UserId = positionModel.UserId == 1 ? user.Id : positionModel.UserId;

                var page = _positionService.AdvancedPagedSearchedAll(positionModel);
                var entities = page.Entities.ToList();
                //set IsAuthenticated for every expert profile to true if current user id == expert profile's userid
                foreach (var entity in entities.Where(entity => entity.CompanyProfile.UserId == user.Id))
                {
                    entity.IsAuthenticated = true;
                }
                page.Entities = entities;
                return page;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

        public IPage<Position> ListAdvancedSearchSome(AdvancedSearchModelPosition positionModel)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                //set profile model's userid to current user id 
                positionModel.UserId = positionModel.UserId == 1 ? user.Id : positionModel.UserId;

                var page = _positionService.AdvancedPagedSearchedSome(positionModel);
                var entities = page.Entities.ToList();
                //set IsAuthenticated for every expert profile to true if current user id == expert profile's userid
                foreach (var entity in entities.Where(entity => entity.CompanyProfile.UserId == user.Id))
                {
                    entity.IsAuthenticated = true;
                }
                page.Entities = entities;
                return page;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

        public HttpResponseMessage PostPosition(Position position)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                position.CompanyProfile = _companyProfileService.GetAll().First(c => c.UserId == user.Id);

              
                // first save the parent entity in order to autogenerate his Id
                _positionService.SaveOrUpdate(position);

                //create directories for the new Position
                var di = new DirectoryInfo(HttpContext.Current.Server.MapPath("~/Content/Uploads/" +
                                                          Path.Combine(user.Username, "PositionProfiles",
                                                                       position.Id.ToString(), "Photo")));
                di.Create();

                //Save Photo
                var username = _userService.GetUserByUsername(User.Identity.Name).Username;
                var fileNamePhoto = position.Photo.Substring(position.Photo.IndexOf("/250X250_") + 9);
                var directoryPhoto = HttpContext.Current.Server.MapPath("~/Content/Uploads/" +
                                                    Path.Combine(username, "PositionProfiles", position.Id.ToString(),
                                                                 "Photo"));

                var dirPhoto = new DirectoryInfo(directoryPhoto);
                if (!dirPhoto.Exists)
                    dirPhoto.Create();
                foreach (var fi in dirPhoto.GetFiles())
                {
                    if (!fi.FullName.Contains("\\250X250_" + fileNamePhoto) &&
                        !fi.FullName.Contains("\\150X150_" + fileNamePhoto) &&
                        !fi.FullName.Contains("\\80X80_" + fileNamePhoto))
                    {
                        fi.Delete();
                    }
                }
              
                position.StartDate = position.StartDate.HasValue ? position.StartDate.Value.AddHours(12) : new DateTime(); 
                _positionService.SaveOrUpdate(position);

                var response = Request.CreateResponse(HttpStatusCode.Created, position.Id);
                return response;
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
        }

        public HttpResponseMessage Update(Position position)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);

                //if the Position belongs to current user save changes
                if (position.CompanyProfile.UserId == user.Id)
                {
                    // load the old entity from the DB and manually set all its new property values
                    var oldPosition = _positionService.GetById(position.Id);
                    oldPosition.Title = position.Title;
                    oldPosition.Description = position.Description;
                    oldPosition.StartDate = position.StartDate;
                    oldPosition.Duration = position.Duration;
                    oldPosition.Location = position.Location;
                    oldPosition.JobType = position.JobType;
                    oldPosition.CountryId = position.CountryId;

                    var categoriesIds = position.Categories.Select(s => s.Id);
                    var technologiesIds = position.Technologies.Select(s => s.Id);
                    //from all the categories/technologies we find those that exist in the new Position, by ID
                    var categories = _categoryService.GetAll().Where(c => categoriesIds.Contains(c.Id)).ToList();
                    var technologies = _technologyService.GetAll().Where(t => technologiesIds.Contains(t.Id)).ToList();

                    // clean the old relationships and set the new ones
                    oldPosition.Categories.Clear();
                    oldPosition.Technologies.Clear();

                    // categories/technologies require to set their foreign key because they are "one to many" relationship
                    // for the "many to many" it is enough to add it to the list
                    //add the categories/technologies of the new Position to the old Position
                    categories.ForEach(c => oldPosition.Categories.Add(c));
                    technologies.ForEach(t => oldPosition.Technologies.Add(t));

                    _positionService.SaveOrUpdate(oldPosition);
                    return new HttpResponseMessage(HttpStatusCode.OK);
                }
                //else if the profile doesn't belong to current user return "error" which means to render "you are not allowed...." message on client side
                return new HttpResponseMessage(HttpStatusCode.Forbidden);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

        public HttpResponseMessage DeletePosition(int positionId)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                var position = _positionService.GetById(positionId);
                 //if the profile belongs to current user save changes
                if (position.CompanyProfile.UserId == user.Id)
                {
                    _positionService.Delete(position);
                    return new HttpResponseMessage(HttpStatusCode.NoContent);
                }
                //else if the profile doesn't belong to current user return "error"
                //which means to render "you are not allowed...." message on client side
                return new HttpResponseMessage(HttpStatusCode.Forbidden);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return new HttpResponseMessage(HttpStatusCode.NotFound);
            }
        }

        public HttpResponseMessage SetAsDefault(Position positionProfile)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var position = _positionService.GetById(positionProfile.Id);
                var user = position.CompanyProfile.User;
                //set isdefault=false to all other profiles that belong to current user
                if (user.ExpertProfiles != null)
                {
                    user.ExpertProfiles.ToList().ForEach(e => e.IsDefault = false);
                }
                if (user.CompanyProfiles != null)
                {
                    user.CompanyProfiles.ToList().ForEach(c => c.IsDefault = false);
                    foreach (var positionX in from companyProfileX in user.CompanyProfiles
                                            where companyProfileX.Positions != null
                                            from positionX in
                                                user.CompanyProfiles.SelectMany(company => company.Positions)
                                            select positionX)
                    {
                        positionX.IsDefault = false;
                    }
                }
                position.IsDefault = true;
                _positionService.SaveOrUpdate(position);
                return new HttpResponseMessage(HttpStatusCode.OK);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }
    }
}